{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total memory 17071734784\n",
      "Free memory 17061249024\n",
      "Used memory 10485760\n"
     ]
    }
   ],
   "source": [
    "from pynvml import *\n",
    "nvmlInit()\n",
    "import os\n",
    "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"1\"\n",
    "handle = nvmlDeviceGetHandleByIndex(1)\n",
    "info = nvmlDeviceGetMemoryInfo(handle)\n",
    "print(\"Total memory\", info.total)\n",
    "print(\"Free memory\", info.free)\n",
    "print(\"Used memory\", info.used)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -*- coding: utf-8 -*-\n",
    "\"\"\"\n",
    "# @file name  : train_lenet.py\n",
    "# @author     : tingsongyu\n",
    "# @date       : 2019-09-07 10:08:00\n",
    "# @brief      : 人民币分类模型训练\n",
    "\"\"\"\n",
    "\"\"\"\n",
    "# @file name  : train_lenet_gpu_copy.py\n",
    "# @modified by: greebear\n",
    "# @date       : 2019-10-26 13:25:00\n",
    "# @brief      : 猫狗分类模型训练\n",
    "\"\"\"\n",
    "import os\n",
    "import random\n",
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "from torch.utils.data import DataLoader\n",
    "import torchvision.transforms as transforms\n",
    "import torch.optim as optim\n",
    "from matplotlib import pyplot as plt\n",
    "from lenet import LeNet, MyNet\n",
    "from DogCat_dataset import DogCatDataset\n",
    "\n",
    "\n",
    "def set_seed(seed=1):\n",
    "    random.seed(seed)\n",
    "    np.random.seed(seed)\n",
    "    torch.manual_seed(seed)\n",
    "    torch.cuda.manual_seed(seed)\n",
    "\n",
    "\n",
    "set_seed()  # 设置随机种子\n",
    "\n",
    "# 参数设置\n",
    "MAX_EPOCH = 40\n",
    "BATCH_SIZE = 512\n",
    "LR = 1e-3\n",
    "log_interval = 10\n",
    "val_interval = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ============================ step 1/5 数据 ============================\n",
    "\n",
    "split_dir = os.path.join(\"..\", \"data\", \"cad_split\")\n",
    "train_dir = os.path.join(split_dir, \"train\")\n",
    "valid_dir = os.path.join(split_dir, \"valid\")\n",
    "\n",
    "norm_mean = [0.485, 0.456, 0.406]\n",
    "norm_std = [0.229, 0.224, 0.225]\n",
    "\n",
    "\n",
    "train_transform = transforms.Compose([\n",
    "    transforms.Resize((224, 224)),\n",
    "    transforms.RandomHorizontalFlip(p=0.5),\n",
    "    transforms.RandomGrayscale(p=0.1),\n",
    "    transforms.RandomApply([transforms.RandomCrop(200, padding=24, padding_mode='reflect')], p=0.2),\n",
    "    transforms.Resize((224, 224)),\n",
    "    transforms.ToTensor(),\n",
    "#     transforms.RandomErasing(p=0.2, scale=(0.02, 0.33), ratio=(0.3, 3.3), value='random'),\n",
    "    transforms.Normalize(norm_mean, norm_std),\n",
    "])\n",
    "\n",
    "valid_transform = transforms.Compose([\n",
    "    transforms.Resize((224, 224)),\n",
    "    transforms.ToTensor(),\n",
    "    transforms.Normalize(norm_mean, norm_std),\n",
    "])\n",
    "\n",
    "# 构建MyDataset实例\n",
    "train_data = DogCatDataset(data_dir=train_dir, transform=train_transform)\n",
    "valid_data = DogCatDataset(data_dir=valid_dir, transform=valid_transform)\n",
    "\n",
    "# 构建DataLoder\n",
    "train_loader = DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True, num_workers=16)\n",
    "valid_loader = DataLoader(dataset=valid_data, batch_size=BATCH_SIZE, num_workers=16)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ============================ step 2/5 模型 ============================\n",
    "\n",
    "net = MyNet(classes=2)\n",
    "net.initialize_weights()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MyNet(\n",
       "  (conv1): Conv2d(3, 16, kernel_size=(7, 7), stride=(1, 1), padding=(3, 3))\n",
       "  (bn1): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (conv2_1): Conv2d(16, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n",
       "  (bn2_1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (conv2_2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (bn2_2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (conv3_1): Conv2d(32, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n",
       "  (bn3_1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (conv3_2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (bn3_2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (conv4_1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n",
       "  (bn4_1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (conv4_2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (bn4_2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (avg_pool): AdaptiveAvgPool2d(output_size=(1, 1))\n",
       "  (bn5_avg): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (max_pool): AdaptiveMaxPool2d(output_size=(1, 1))\n",
       "  (bn5_max): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (dropout1): Dropout(p=0.25, inplace=False)\n",
       "  (fc1): Linear(in_features=256, out_features=128, bias=True)\n",
       "  (dropout2): Dropout(p=0.5, inplace=False)\n",
       "  (fc2): Linear(in_features=128, out_features=2, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.to(\"cuda\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ============================ step 3/5 损失函数 ============================\n",
    "criterion = nn.CrossEntropyLoss()   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ============================ step 4/5 优化器 ============================\n",
    "optimizer = optim.Adam(net.parameters(), lr=LR, betas=(0.9, 0.999), eps=1e-08, weight_decay=1e-1)                        # 选择优化器\n",
    "scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)     # 设置学习率下降策略"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# inputs.to(\"cuda\").device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------------------------------------------------------------\n",
      "        Layer (type)               Output Shape         Param #\n",
      "================================================================\n",
      "            Conv2d-1         [-1, 16, 512, 512]           2,368\n",
      "       BatchNorm2d-2         [-1, 16, 512, 512]              32\n",
      "            Conv2d-3         [-1, 32, 256, 256]           4,640\n",
      "       BatchNorm2d-4         [-1, 32, 256, 256]              64\n",
      "            Conv2d-5         [-1, 32, 256, 256]           9,248\n",
      "       BatchNorm2d-6         [-1, 32, 256, 256]              64\n",
      "            Conv2d-7         [-1, 64, 128, 128]          18,496\n",
      "       BatchNorm2d-8         [-1, 64, 128, 128]             128\n",
      "            Conv2d-9         [-1, 64, 128, 128]          36,928\n",
      "      BatchNorm2d-10         [-1, 64, 128, 128]             128\n",
      "           Conv2d-11          [-1, 128, 64, 64]          73,856\n",
      "      BatchNorm2d-12          [-1, 128, 64, 64]             256\n",
      "           Conv2d-13          [-1, 128, 64, 64]         147,584\n",
      "      BatchNorm2d-14          [-1, 128, 64, 64]             256\n",
      "AdaptiveAvgPool2d-15            [-1, 128, 1, 1]               0\n",
      "      BatchNorm2d-16            [-1, 128, 1, 1]             256\n",
      "AdaptiveMaxPool2d-17            [-1, 128, 1, 1]               0\n",
      "      BatchNorm2d-18            [-1, 128, 1, 1]             256\n",
      "          Dropout-19                  [-1, 256]               0\n",
      "           Linear-20                  [-1, 128]          32,896\n",
      "          Dropout-21                  [-1, 128]               0\n",
      "           Linear-22                    [-1, 2]             258\n",
      "================================================================\n",
      "Total params: 327,714\n",
      "Trainable params: 327,714\n",
      "Non-trainable params: 0\n",
      "----------------------------------------------------------------\n",
      "Input size (MB): 3.00\n",
      "Forward/backward pass size (MB): 176.01\n",
      "Params size (MB): 1.25\n",
      "Estimated Total Size (MB): 180.26\n",
      "----------------------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "from torchsummary import summary\n",
    "summary(net, input_size=(3, 512, 512))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "valid_acc = list()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training:Epoch[000/040] Iteration[010/040] Loss: 1.1178 Acc:54.02%\n",
      "Training:Epoch[000/040] Iteration[020/040] Loss: 0.8828 Acc:55.31%\n",
      "Training:Epoch[000/040] Iteration[030/040] Loss: 0.7864 Acc:56.40%\n",
      "Training:Epoch[000/040] Iteration[040/040] Loss: 0.7714 Acc:57.56%\n",
      "Valid:\t Epoch[000/040] Iteration[005/005] Loss: 3.3157 【Acc:58.48%】\n",
      "Training:Epoch[001/040] Iteration[010/040] Loss: 0.6886 Acc:61.88%\n",
      "Training:Epoch[001/040] Iteration[020/040] Loss: 0.6504 Acc:62.91%\n",
      "Training:Epoch[001/040] Iteration[030/040] Loss: 0.6412 Acc:63.41%\n",
      "Training:Epoch[001/040] Iteration[040/040] Loss: 0.6384 Acc:63.69%\n",
      "Valid:\t Epoch[001/040] Iteration[005/005] Loss: 3.3017 【Acc:58.04%】\n",
      "Training:Epoch[002/040] Iteration[010/040] Loss: 0.6425 Acc:64.77%\n",
      "Training:Epoch[002/040] Iteration[020/040] Loss: 0.6134 Acc:65.83%\n",
      "Training:Epoch[002/040] Iteration[030/040] Loss: 0.6023 Acc:66.45%\n",
      "Training:Epoch[002/040] Iteration[040/040] Loss: 0.5837 Acc:66.97%\n",
      "Valid:\t Epoch[002/040] Iteration[005/005] Loss: 3.8508 【Acc:54.16%】\n",
      "Training:Epoch[003/040] Iteration[010/040] Loss: 0.5976 Acc:68.96%\n",
      "Training:Epoch[003/040] Iteration[020/040] Loss: 0.5850 Acc:68.65%\n",
      "Training:Epoch[003/040] Iteration[030/040] Loss: 0.5565 Acc:69.48%\n",
      "Training:Epoch[003/040] Iteration[040/040] Loss: 0.5313 Acc:70.39%\n",
      "Valid:\t Epoch[003/040] Iteration[005/005] Loss: 3.2473 【Acc:63.44%】\n",
      "Training:Epoch[004/040] Iteration[010/040] Loss: 0.5724 Acc:70.47%\n",
      "Training:Epoch[004/040] Iteration[020/040] Loss: 0.5265 Acc:72.19%\n",
      "Training:Epoch[004/040] Iteration[030/040] Loss: 0.5318 Acc:72.84%\n",
      "Training:Epoch[004/040] Iteration[040/040] Loss: 0.5121 Acc:73.39%\n",
      "Valid:\t Epoch[004/040] Iteration[005/005] Loss: 3.8059 【Acc:54.88%】\n",
      "Training:Epoch[005/040] Iteration[010/040] Loss: 0.4989 Acc:75.74%\n",
      "Training:Epoch[005/040] Iteration[020/040] Loss: 0.4874 Acc:76.50%\n",
      "Training:Epoch[005/040] Iteration[030/040] Loss: 0.4847 Acc:76.63%\n",
      "Training:Epoch[005/040] Iteration[040/040] Loss: 0.4635 Acc:77.15%\n",
      "Valid:\t Epoch[005/040] Iteration[005/005] Loss: 3.1010 【Acc:66.60%】\n",
      "Training:Epoch[006/040] Iteration[010/040] Loss: 0.4938 Acc:77.17%\n",
      "Training:Epoch[006/040] Iteration[020/040] Loss: 0.4772 Acc:77.43%\n",
      "Training:Epoch[006/040] Iteration[030/040] Loss: 0.4587 Acc:77.85%\n",
      "Training:Epoch[006/040] Iteration[040/040] Loss: 0.4528 Acc:78.23%\n",
      "Valid:\t Epoch[006/040] Iteration[005/005] Loss: 3.4164 【Acc:62.24%】\n",
      "Training:Epoch[007/040] Iteration[010/040] Loss: 0.4628 Acc:78.81%\n",
      "Training:Epoch[007/040] Iteration[020/040] Loss: 0.4331 Acc:79.63%\n",
      "Training:Epoch[007/040] Iteration[030/040] Loss: 0.4104 Acc:80.42%\n",
      "Training:Epoch[007/040] Iteration[040/040] Loss: 0.4186 Acc:80.70%\n",
      "Valid:\t Epoch[007/040] Iteration[005/005] Loss: 3.0132 【Acc:67.04%】\n",
      "Training:Epoch[008/040] Iteration[010/040] Loss: 0.4619 Acc:78.81%\n",
      "Training:Epoch[008/040] Iteration[020/040] Loss: 0.4225 Acc:80.25%\n",
      "Training:Epoch[008/040] Iteration[030/040] Loss: 0.4064 Acc:80.83%\n",
      "Training:Epoch[008/040] Iteration[040/040] Loss: 0.3985 Acc:81.41%\n",
      "Valid:\t Epoch[008/040] Iteration[005/005] Loss: 3.0642 【Acc:61.40%】\n",
      "Training:Epoch[009/040] Iteration[010/040] Loss: 0.4351 Acc:79.55%\n",
      "Training:Epoch[009/040] Iteration[020/040] Loss: 0.4026 Acc:80.79%\n",
      "Training:Epoch[009/040] Iteration[030/040] Loss: 0.3782 Acc:81.78%\n",
      "Training:Epoch[009/040] Iteration[040/040] Loss: 0.3635 Acc:82.45%\n",
      "Valid:\t Epoch[009/040] Iteration[005/005] Loss: 2.9035 【Acc:63.32%】\n",
      "Training:Epoch[010/040] Iteration[010/040] Loss: 0.3489 Acc:86.07%\n",
      "Training:Epoch[010/040] Iteration[020/040] Loss: 0.3154 Acc:87.02%\n",
      "Training:Epoch[010/040] Iteration[030/040] Loss: 0.2915 Acc:87.85%\n",
      "Training:Epoch[010/040] Iteration[040/040] Loss: 0.2888 Acc:88.18%\n",
      "Valid:\t Epoch[010/040] Iteration[005/005] Loss: 1.4742 【Acc:88.80%】\n",
      "Training:Epoch[011/040] Iteration[010/040] Loss: 0.2873 Acc:88.71%\n",
      "Training:Epoch[011/040] Iteration[020/040] Loss: 0.2720 Acc:89.42%\n",
      "Training:Epoch[011/040] Iteration[030/040] Loss: 0.2709 Acc:89.56%\n",
      "Training:Epoch[011/040] Iteration[040/040] Loss: 0.2687 Acc:89.68%\n",
      "Valid:\t Epoch[011/040] Iteration[005/005] Loss: 1.5211 【Acc:88.32%】\n",
      "Training:Epoch[012/040] Iteration[010/040] Loss: 0.2606 Acc:90.00%\n",
      "Training:Epoch[012/040] Iteration[020/040] Loss: 0.2556 Acc:89.89%\n",
      "Training:Epoch[012/040] Iteration[030/040] Loss: 0.2579 Acc:90.02%\n",
      "Training:Epoch[012/040] Iteration[040/040] Loss: 0.2462 Acc:90.16%\n",
      "Valid:\t Epoch[012/040] Iteration[005/005] Loss: 1.4192 【Acc:88.44%】\n",
      "Training:Epoch[013/040] Iteration[010/040] Loss: 0.2521 Acc:90.57%\n",
      "Training:Epoch[013/040] Iteration[020/040] Loss: 0.2395 Acc:90.83%\n",
      "Training:Epoch[013/040] Iteration[030/040] Loss: 0.2402 Acc:90.88%\n",
      "Training:Epoch[013/040] Iteration[040/040] Loss: 0.2425 Acc:91.11%\n",
      "Valid:\t Epoch[013/040] Iteration[005/005] Loss: 1.3977 【Acc:88.96%】\n",
      "Training:Epoch[014/040] Iteration[010/040] Loss: 0.2582 Acc:90.53%\n",
      "Training:Epoch[014/040] Iteration[020/040] Loss: 0.2404 Acc:90.99%\n",
      "Training:Epoch[014/040] Iteration[030/040] Loss: 0.2357 Acc:91.17%\n",
      "Training:Epoch[014/040] Iteration[040/040] Loss: 0.2356 Acc:91.13%\n",
      "Valid:\t Epoch[014/040] Iteration[005/005] Loss: 1.3999 【Acc:88.92%】\n",
      "Training:Epoch[015/040] Iteration[010/040] Loss: 0.2375 Acc:91.15%\n",
      "Training:Epoch[015/040] Iteration[020/040] Loss: 0.2254 Acc:91.57%\n",
      "Training:Epoch[015/040] Iteration[030/040] Loss: 0.2272 Acc:91.67%\n",
      "Training:Epoch[015/040] Iteration[040/040] Loss: 0.2137 Acc:91.88%\n",
      "Valid:\t Epoch[015/040] Iteration[005/005] Loss: 1.6697 【Acc:84.96%】\n",
      "Training:Epoch[016/040] Iteration[010/040] Loss: 0.2290 Acc:91.29%\n",
      "Training:Epoch[016/040] Iteration[020/040] Loss: 0.2194 Acc:91.59%\n",
      "Training:Epoch[016/040] Iteration[030/040] Loss: 0.2190 Acc:91.76%\n",
      "Training:Epoch[016/040] Iteration[040/040] Loss: 0.2013 Acc:92.02%\n",
      "Valid:\t Epoch[016/040] Iteration[005/005] Loss: 1.2007 【Acc:90.92%】\n",
      "Training:Epoch[017/040] Iteration[010/040] Loss: 0.2081 Acc:92.52%\n",
      "Training:Epoch[017/040] Iteration[020/040] Loss: 0.2007 Acc:92.70%\n",
      "Training:Epoch[017/040] Iteration[030/040] Loss: 0.1974 Acc:92.90%\n",
      "Training:Epoch[017/040] Iteration[040/040] Loss: 0.1987 Acc:93.01%\n",
      "Valid:\t Epoch[017/040] Iteration[005/005] Loss: 1.2283 【Acc:89.60%】\n",
      "Training:Epoch[018/040] Iteration[010/040] Loss: 0.2282 Acc:91.48%\n",
      "Training:Epoch[018/040] Iteration[020/040] Loss: 0.2081 Acc:92.19%\n",
      "Training:Epoch[018/040] Iteration[030/040] Loss: 0.2138 Acc:92.26%\n",
      "Training:Epoch[018/040] Iteration[040/040] Loss: 0.1867 Acc:92.62%\n",
      "Valid:\t Epoch[018/040] Iteration[005/005] Loss: 1.2063 【Acc:88.84%】\n",
      "Training:Epoch[019/040] Iteration[010/040] Loss: 0.1994 Acc:92.70%\n",
      "Training:Epoch[019/040] Iteration[020/040] Loss: 0.1981 Acc:92.89%\n",
      "Training:Epoch[019/040] Iteration[030/040] Loss: 0.1932 Acc:93.07%\n",
      "Training:Epoch[019/040] Iteration[040/040] Loss: 0.1775 Acc:93.51%\n",
      "Valid:\t Epoch[019/040] Iteration[005/005] Loss: 1.2940 【Acc:89.32%】\n",
      "Training:Epoch[020/040] Iteration[010/040] Loss: 0.1854 Acc:93.67%\n",
      "Training:Epoch[020/040] Iteration[020/040] Loss: 0.1838 Acc:93.67%\n",
      "Training:Epoch[020/040] Iteration[030/040] Loss: 0.1652 Acc:94.11%\n",
      "Training:Epoch[020/040] Iteration[040/040] Loss: 0.1619 Acc:94.22%\n",
      "Valid:\t Epoch[020/040] Iteration[005/005] Loss: 0.8933 【Acc:93.80%】\n",
      "Training:Epoch[021/040] Iteration[010/040] Loss: 0.1636 Acc:94.80%\n",
      "Training:Epoch[021/040] Iteration[020/040] Loss: 0.1556 Acc:95.12%\n",
      "Training:Epoch[021/040] Iteration[030/040] Loss: 0.1565 Acc:95.15%\n",
      "Training:Epoch[021/040] Iteration[040/040] Loss: 0.1618 Acc:95.17%\n",
      "Valid:\t Epoch[021/040] Iteration[005/005] Loss: 0.8947 【Acc:93.72%】\n",
      "Training:Epoch[022/040] Iteration[010/040] Loss: 0.1533 Acc:95.37%\n",
      "Training:Epoch[022/040] Iteration[020/040] Loss: 0.1560 Acc:95.41%\n",
      "Training:Epoch[022/040] Iteration[030/040] Loss: 0.1587 Acc:95.35%\n",
      "Training:Epoch[022/040] Iteration[040/040] Loss: 0.1637 Acc:95.42%\n",
      "Valid:\t Epoch[022/040] Iteration[005/005] Loss: 0.8401 【Acc:94.28%】\n",
      "Training:Epoch[023/040] Iteration[010/040] Loss: 0.1476 Acc:95.76%\n",
      "Training:Epoch[023/040] Iteration[020/040] Loss: 0.1472 Acc:95.74%\n",
      "Training:Epoch[023/040] Iteration[030/040] Loss: 0.1567 Acc:95.55%\n",
      "Training:Epoch[023/040] Iteration[040/040] Loss: 0.1524 Acc:95.62%\n",
      "Valid:\t Epoch[023/040] Iteration[005/005] Loss: 0.8489 【Acc:93.96%】\n",
      "Training:Epoch[024/040] Iteration[010/040] Loss: 0.1525 Acc:95.23%\n",
      "Training:Epoch[024/040] Iteration[020/040] Loss: 0.1480 Acc:95.34%\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training:Epoch[024/040] Iteration[030/040] Loss: 0.1490 Acc:95.38%\n",
      "Training:Epoch[024/040] Iteration[040/040] Loss: 0.1386 Acc:95.52%\n",
      "Valid:\t Epoch[024/040] Iteration[005/005] Loss: 0.8240 【Acc:94.28%】\n",
      "Training:Epoch[025/040] Iteration[010/040] Loss: 0.1527 Acc:95.45%\n",
      "Training:Epoch[025/040] Iteration[020/040] Loss: 0.1425 Acc:95.63%\n",
      "Training:Epoch[025/040] Iteration[030/040] Loss: 0.1499 Acc:95.61%\n",
      "Training:Epoch[025/040] Iteration[040/040] Loss: 0.1335 Acc:95.67%\n",
      "Valid:\t Epoch[025/040] Iteration[005/005] Loss: 0.8042 【Acc:94.80%】\n",
      "Training:Epoch[026/040] Iteration[010/040] Loss: 0.1426 Acc:95.66%\n",
      "Training:Epoch[026/040] Iteration[020/040] Loss: 0.1384 Acc:95.83%\n",
      "Training:Epoch[026/040] Iteration[030/040] Loss: 0.1407 Acc:95.84%\n",
      "Training:Epoch[026/040] Iteration[040/040] Loss: 0.1457 Acc:95.69%\n",
      "Valid:\t Epoch[026/040] Iteration[005/005] Loss: 0.8100 【Acc:94.52%】\n",
      "Training:Epoch[027/040] Iteration[010/040] Loss: 0.1411 Acc:95.96%\n",
      "Training:Epoch[027/040] Iteration[020/040] Loss: 0.1411 Acc:95.87%\n",
      "Training:Epoch[027/040] Iteration[030/040] Loss: 0.1379 Acc:95.98%\n",
      "Training:Epoch[027/040] Iteration[040/040] Loss: 0.1385 Acc:95.89%\n",
      "Valid:\t Epoch[027/040] Iteration[005/005] Loss: 0.8206 【Acc:94.36%】\n",
      "Training:Epoch[028/040] Iteration[010/040] Loss: 0.1358 Acc:96.33%\n",
      "Training:Epoch[028/040] Iteration[020/040] Loss: 0.1428 Acc:95.93%\n",
      "Training:Epoch[028/040] Iteration[030/040] Loss: 0.1335 Acc:96.07%\n",
      "Training:Epoch[028/040] Iteration[040/040] Loss: 0.1355 Acc:96.10%\n",
      "Valid:\t Epoch[028/040] Iteration[005/005] Loss: 0.7927 【Acc:94.60%】\n",
      "Training:Epoch[029/040] Iteration[010/040] Loss: 0.1365 Acc:96.13%\n",
      "Training:Epoch[029/040] Iteration[020/040] Loss: 0.1382 Acc:96.10%\n",
      "Training:Epoch[029/040] Iteration[030/040] Loss: 0.1387 Acc:96.00%\n",
      "Training:Epoch[029/040] Iteration[040/040] Loss: 0.1420 Acc:95.95%\n",
      "Valid:\t Epoch[029/040] Iteration[005/005] Loss: 0.8016 【Acc:94.36%】\n",
      "Training:Epoch[030/040] Iteration[010/040] Loss: 0.1307 Acc:96.50%\n",
      "Training:Epoch[030/040] Iteration[020/040] Loss: 0.1336 Acc:96.35%\n",
      "Training:Epoch[030/040] Iteration[030/040] Loss: 0.1333 Acc:96.39%\n",
      "Training:Epoch[030/040] Iteration[040/040] Loss: 0.1387 Acc:96.38%\n",
      "Valid:\t Epoch[030/040] Iteration[005/005] Loss: 0.7630 【Acc:95.08%】\n",
      "Training:Epoch[031/040] Iteration[010/040] Loss: 0.1310 Acc:96.17%\n",
      "Training:Epoch[031/040] Iteration[020/040] Loss: 0.1277 Acc:96.35%\n",
      "Training:Epoch[031/040] Iteration[030/040] Loss: 0.1301 Acc:96.52%\n",
      "Training:Epoch[031/040] Iteration[040/040] Loss: 0.1379 Acc:96.48%\n",
      "Valid:\t Epoch[031/040] Iteration[005/005] Loss: 0.7643 【Acc:94.96%】\n",
      "Training:Epoch[032/040] Iteration[010/040] Loss: 0.1306 Acc:96.54%\n",
      "Training:Epoch[032/040] Iteration[020/040] Loss: 0.1307 Acc:96.49%\n",
      "Training:Epoch[032/040] Iteration[030/040] Loss: 0.1347 Acc:96.44%\n",
      "Training:Epoch[032/040] Iteration[040/040] Loss: 0.1283 Acc:96.50%\n",
      "Valid:\t Epoch[032/040] Iteration[005/005] Loss: 0.7716 【Acc:94.92%】\n",
      "Training:Epoch[033/040] Iteration[010/040] Loss: 0.1267 Acc:96.78%\n",
      "Training:Epoch[033/040] Iteration[020/040] Loss: 0.1262 Acc:96.82%\n",
      "Training:Epoch[033/040] Iteration[030/040] Loss: 0.1320 Acc:96.62%\n",
      "Training:Epoch[033/040] Iteration[040/040] Loss: 0.1252 Acc:96.57%\n",
      "Valid:\t Epoch[033/040] Iteration[005/005] Loss: 0.7646 【Acc:94.68%】\n",
      "Training:Epoch[034/040] Iteration[010/040] Loss: 0.1295 Acc:96.48%\n",
      "Training:Epoch[034/040] Iteration[020/040] Loss: 0.1322 Acc:96.44%\n",
      "Training:Epoch[034/040] Iteration[030/040] Loss: 0.1233 Acc:96.61%\n",
      "Training:Epoch[034/040] Iteration[040/040] Loss: 0.1243 Acc:96.65%\n",
      "Valid:\t Epoch[034/040] Iteration[005/005] Loss: 0.7628 【Acc:94.72%】\n",
      "Training:Epoch[035/040] Iteration[010/040] Loss: 0.1300 Acc:96.46%\n",
      "Training:Epoch[035/040] Iteration[020/040] Loss: 0.1287 Acc:96.49%\n",
      "Training:Epoch[035/040] Iteration[030/040] Loss: 0.1329 Acc:96.39%\n",
      "Training:Epoch[035/040] Iteration[040/040] Loss: 0.1285 Acc:96.43%\n",
      "Valid:\t Epoch[035/040] Iteration[005/005] Loss: 0.7685 【Acc:94.80%】\n",
      "Training:Epoch[036/040] Iteration[010/040] Loss: 0.1295 Acc:96.72%\n",
      "Training:Epoch[036/040] Iteration[020/040] Loss: 0.1327 Acc:96.37%\n",
      "Training:Epoch[036/040] Iteration[030/040] Loss: 0.1285 Acc:96.36%\n",
      "Training:Epoch[036/040] Iteration[040/040] Loss: 0.1333 Acc:96.36%\n",
      "Valid:\t Epoch[036/040] Iteration[005/005] Loss: 0.7654 【Acc:94.84%】\n",
      "Training:Epoch[037/040] Iteration[010/040] Loss: 0.1239 Acc:96.95%\n",
      "Training:Epoch[037/040] Iteration[020/040] Loss: 0.1272 Acc:96.83%\n",
      "Training:Epoch[037/040] Iteration[030/040] Loss: 0.1350 Acc:96.70%\n",
      "Training:Epoch[037/040] Iteration[040/040] Loss: 0.1410 Acc:96.68%\n",
      "Valid:\t Epoch[037/040] Iteration[005/005] Loss: 0.7612 【Acc:94.88%】\n",
      "Training:Epoch[038/040] Iteration[010/040] Loss: 0.1293 Acc:96.33%\n",
      "Training:Epoch[038/040] Iteration[020/040] Loss: 0.1286 Acc:96.33%\n",
      "Training:Epoch[038/040] Iteration[030/040] Loss: 0.1234 Acc:96.54%\n",
      "Training:Epoch[038/040] Iteration[040/040] Loss: 0.1307 Acc:96.44%\n",
      "Valid:\t Epoch[038/040] Iteration[005/005] Loss: 0.7628 【Acc:94.88%】\n",
      "Training:Epoch[039/040] Iteration[010/040] Loss: 0.1312 Acc:96.35%\n",
      "Training:Epoch[039/040] Iteration[020/040] Loss: 0.1261 Acc:96.50%\n",
      "Training:Epoch[039/040] Iteration[030/040] Loss: 0.1252 Acc:96.53%\n",
      "Training:Epoch[039/040] Iteration[040/040] Loss: 0.1229 Acc:96.52%\n",
      "Valid:\t Epoch[039/040] Iteration[005/005] Loss: 0.7620 【Acc:94.76%】\n"
     ]
    }
   ],
   "source": [
    "# ============================ step 5/5 训练 ============================\n",
    "train_curve = list()\n",
    "valid_curve = list()\n",
    "\n",
    "for epoch in range(MAX_EPOCH):\n",
    "\n",
    "    loss_mean = 0.\n",
    "    correct = 0.\n",
    "    total = 0.\n",
    "\n",
    "    net.train()\n",
    "    for i, data in enumerate(train_loader):\n",
    "        # forward\n",
    "        inputs, labels = data\n",
    "        inputs = inputs.to(\"cuda\")\n",
    "        labels = labels.to(\"cuda\")\n",
    "        outputs = net(inputs)\n",
    "\n",
    "        # backward\n",
    "        optimizer.zero_grad()\n",
    "        loss = criterion(outputs, labels)\n",
    "        loss.backward()\n",
    "\n",
    "        # update weights\n",
    "        optimizer.step()\n",
    "\n",
    "        # 统计分类情况\n",
    "        _, predicted = torch.max(outputs.data, 1)\n",
    "        total += labels.size(0)\n",
    "        correct += (predicted == labels).squeeze().sum().cpu().numpy()\n",
    "\n",
    "        # 打印训练信息\n",
    "        loss_mean += loss.item()\n",
    "        train_curve.append(loss.item())\n",
    "        if (i+1) % log_interval == 0:\n",
    "            loss_mean = loss_mean / log_interval\n",
    "            print(\"Training:Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}\".format(\n",
    "                epoch, MAX_EPOCH, i+1, len(train_loader), loss_mean, correct / total))\n",
    "            loss_mean = 0.\n",
    "\n",
    "    scheduler.step()  # 更新学习率\n",
    "\n",
    "    # validate the model\n",
    "    if (epoch+1) % val_interval == 0:\n",
    "\n",
    "        correct_val = 0.\n",
    "        total_val = 0.\n",
    "        loss_val = 0.\n",
    "        net.eval()\n",
    "        with torch.no_grad():\n",
    "            for j, data in enumerate(valid_loader):\n",
    "                inputs, labels = data\n",
    "                inputs = inputs.to(\"cuda\")\n",
    "                labels = labels.to(\"cuda\")\n",
    "                outputs = net(inputs)\n",
    "                loss = criterion(outputs, labels)\n",
    "\n",
    "                _, predicted = torch.max(outputs.data, 1)\n",
    "                total_val += labels.size(0)\n",
    "                correct_val += (predicted == labels).squeeze().sum().cpu().numpy()\n",
    "\n",
    "                loss_val += loss.item()\n",
    "\n",
    "            valid_curve.append(loss.item())\n",
    "            valid_acc.append(correct_val / total_val)\n",
    "            print(\"Valid:\\t Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} 【Acc:{:.2%}】\".format(\n",
    "                epoch, MAX_EPOCH, j+1, len(valid_loader), loss_val, correct_val / total_val))\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "train_x = range(len(train_curve))\n",
    "train_y = train_curve\n",
    "\n",
    "train_iters = len(train_loader)\n",
    "valid_x = np.arange(1, len(valid_curve)+1) * train_iters*val_interval # 由于valid中记录的是epochloss，需要对记录点进行转换到iterations\n",
    "valid_y = valid_curve\n",
    "\n",
    "plt.plot(train_x, train_y, label='Train')\n",
    "plt.plot(valid_x, valid_y, label='Valid')\n",
    "\n",
    "plt.legend(loc='upper right')\n",
    "plt.ylabel('loss value')\n",
    "plt.xlabel('Iteration')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9508"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "max(valid_acc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "torch.save(net, \"./2\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
